#!/bin/sh

PWD=`pwd`
XP_DIR=`dirname $PWD`

tmpout="/tmp/cfgmake.$$"

test_cc ()
{
	ext="$1"
	name="$2"

	echo "#include <stdio.h>" > "$tmpout.$ext"
	echo "main () { printf (\"%s\", \"$name\"); }" >> "$tmpout.$ext"

	("$name" -o "$tmpout" "$tmpout.$ext") >/dev/null 2>&1 || { 
		rm -f "$tmpout.$ext"
		return 1
	}

	rm -f "$tmpout.$ext" >/dev/null 2>&1
	"$tmpout"
	rm -f "$tmpout" >/dev/null 2>&1
	return 0
}

test_cc_ident ()
{
	macro="$1"
	compiler="$2"

	echo "
		int main (void) 
		{
		#ifdef $macro
			printf (\"%s\", \"$compiler\");
			return 0;
		#else
			return 1;
		#endif
		}" > "$tmpout.c"

	("$CC" -o "$tmpout" "$tmpout.c") >/dev/null 2>&1 || { 
		rm -f "$tmpout.$c"
		return 1
	}

	rm -f "$tmpout.c" >/dev/null 2>&1
	"$tmpout"
	ret=$?
	rm -f "$tmpout" >/dev/null 2>&1
	return $ret
} 

test_as ()
{
	ext="$1"
	name="$2"

	echo "test_as:" > "$tmpout.$ext"

	("$name" -o "$tmpout" "$tmpout.$ext") >/dev/null 2>&1 || { 
		rm -f "$tmpout.$ext"
		return 1
	}

	rm -f "$tmout" "$tmpout.$ext" >/dev/null 2>&1
	echo $name
	return 0
}


CC=`
	test_cc "c" "cc" || 
	test_cc "c" "c99" || 
	test_cc "c" "gcc" || 
	test_cc "c" "icc"
`
CCC=`
	test_cc "cc" "c++" || 
	test_cc "cc" "g++" || 
	test_cc "cc" "icc" || 
	test_cc "cc" "CC"
`
OBJC=`
	test_cc "m" "cc" || 
	test_cc "m" "gcc"
`
CC_ID=`
	test_cc_ident "__ICC"      "intel" || 
	test_cc_ident "__SUNPRO_C" "sun"   ||
	test_cc_ident "__IBMC__"   "ibm"   ||
	test_cc_ident "__HP_cc"    "hp"    ||
	test_cc_ident "__GNUC__"   "gnu"  
`
AS=`
	test_as "s" "as" ||
	test_as "s" "nasm"
`

echo "Compiler Settings"
echo "  - C compiler:           [$CC]"
echo "  - C++ compiler:         [$CCC]"
echo "  - Objective-C compiler: [$OBJC]"
echo "  - Identity:             [$CC_ID]"
echo "  - Assembler:            [$AS]"

OS=`uname -s | tr "[A-Z]" "[a-z]"`
OS_REL_MAJOR=`uname -r | tr "[A-Z]" "[a-z]" | cut -f1 -d'.'`
OS_REL_MINOR=`uname -r | tr "[A-Z]" "[a-z]" | cut -f2 -d'.'`
ARCH=`uname -p | tr "[A-Z]" "[a-z]"`
#MACHINE=`uname -m | tr "[A-Z]" "[a-z]"`
PTRSIZE=32

case "$ARCH" in
i*86)
	ARCH=x86 
	;;
x86_64)
	ARCH=x86 
	PTRSIZE=64
	;;
esac

case "$OS" in
sunos)
	if [ -x /usr/bin/isainfo ]
	then
		PTRSIZE=`isainfo -b`		
	fi
esac

if [ "$POINTER_SIZE" = "" ]
then
	POINTER_SIZE=$PTRSIZE
fi

cat << __EOF__ >"$tmpout.c"
#include <stdio.h>
int main () { 
	short one=1; char* cp = (char*)&one;
	printf ("%s", (*cp!=0)? "little": "big");
	return 0;
}
__EOF__
"$CC" -o "$tmpout" "$tmpout.c" >/dev/null 2>&1
ENDIAN=`"$tmpout"`
rm -f "$tmpout" "$tmpout.c" >/dev/null 2>&1

echo "System Settings"
echo "  - OS:           [$OS]"
echo "  - Release:      [$OS_REL_MAJOR.$OS_REL_MINOR]"
echo "  - Architecture: [$ARCH]"
#echo "  - Machine:      [$MACHINE]"
echo "  - Endian:       [$ENDIAN]"
echo "  - Pointer size: [$POINTER_SIZE]"

OS=`echo $OS | tr "[a-z]" "[A-Z]"`
OS_REL_MAJOR=`echo $OS_REL_MAJOR | tr "[a-z]" "[A-Z]" | sed 's/[^0-9]//g'`
OS_REL_MINOR=`echo $OS_REL_MINOR | tr "[a-z]" "[A-Z]" | sed 's/[^0-9]//g'`
ARCH=`echo $ARCH | tr "[a-z]" "[A-Z]"`
#MACHINE=`echo $MACHINE | tr "[a-z]" "[A-Z]"`
ENDIAN=`echo $ENDIAN | tr "[a-z]" "[A-Z]"`

SYSTEM_MACROS="-D$OS -DOS_REL_MAJOR=$OS_REL_MAJOR -DOS_REL_MINOR=$OS_REL_MINOR -DARCH_$ARCH -DPOINTER_SIZE=$POINTER_SIZE -DENDIAN_$ENDIAN"

echo "  - SYSTEM_MACROS: $SYSTEM_MACROS"

FEATURE_MACROS=""

add_feature ()
{
	feature="$1"

	"$CC" -o "$tmpout" "$tmpout.c" >/dev/null 2>&1 && FEATURE_MACROS="$FEATURE_MACROS -D$feature"
	rm -f "$tmpout" "$tmpout.c" >/dev/null 2>&1
}

cat << __EOF__ >"$tmpout.c"
int main (void) { long long i; return 0; }
__EOF__
add_feature "HAVE_LONG_LONG"

cat << __EOF__ >"$tmpout.c"
int main (void) { long double i; return 0; }
__EOF__
add_feature "HAVE_LONG_DOUBLE"

cat << __EOF__ >"$tmpout.c"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main () { in_addr_t a; return 0; }
__EOF__
add_feature "HAVE_IN_ADDR_T"

cat << __EOF__ >"$tmpout.c"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main () { in_port_t a; return 0; }
__EOF__
add_feature "HAVE_IN_PORT_T"

cat << __EOF__ >"$tmpout.c"
#include <math.h>
int main () { ceill (10.0); return 0; }
__EOF__
add_feature "HAVE_LONG_DOUBLE_MATH"

cat << __EOF__ >"$tmpout.c"
#include <stdio.h>
#include <stdarg.h>
int main () { va_list ap; vfscanf (stdin, "%s", ap); return 0; }
__EOF__
add_feature "HAVE_VFSCANF"

cat << __EOF__ >"$tmpout.c"
#include <wchar.h>
int main () { wchar_t x = L'a'; return 0; }
__EOF__
add_feature "HAVE_WCHAR"

MISC_MACROS=""

if [ $POINTER_SIZE -eq 32 ]
then
	case "$CC_ID" in
	sun)
		MISC_MACROS="$MISC_MACROS -xarch=v8";;
	gnu) 
		#MISC_MACROS="$MISC_MACROS -ansi -m32";;
		MISC_MACROS="$MISC_MACROS -ansi";;
	esac
elif [ $POINTER_SIZE -eq 64 ]
then
	case "$CC_ID" in
	sun)
		MISC_MACROS="$MISC_MACROS -xarch=v9";;
	gnu) 
		MISC_MACROS="$MISC_MACROS -m64";;
	esac
fi


# -pthread

case "$CC_ID" in
gnu)
	MISC_MACROS="$MISC_MACROS -Wall -Wwrite-strings -Wmissing-prototypes -O2 -fpic"
	
	if [ ! -z "XP_FULL_WCHAR" ]
	then
		#MISC_MACROS="$MISC_MACROS -fshort-wchar"
		MISC_MACROS="$MISC_MACROS"
	fi

	if [ -z "$XP_NON_THREADED" ]
	then
		MISC_MACROS="$MISC_MACROS -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
	fi
	;;
sun)
	MISC_MACROS="$MISC_MACROS +w2 -fast -misalign"
	if [ -z "$XP_NON_THREADED" ]
	then
		MISC_MACROS="$MISC_MACROS -mt -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
	fi
	;;
*)
	;;
esac

CFLAGS="$SYSTEM_MACROS $FEATURE_MACROS $MISC_MACROS"
"$CC" $CFLAGS -o "$tmpout" cfgtypes.c #>/dev/null 2>&1
echo "#ifndef _XP_ITYPES_H_" > ../xp/itypes.h
echo "#define _XP_ITYPES_H_" >> ../xp/itypes.h
"$tmpout" "xp_" >> ../xp/itypes.h
echo "#endif" >> ../xp/itypes.h
rm -f "$tmpout" >/dev/null 2>&1

cat << __EOF__ > makefile.flags
XP_DIR = $XP_DIR

OS = $OS
OS_REL_MAJOR = $OS_REL_MAJOR
OS_REL_MINOR = $OS_REL_MINOR
ARCH = $ARCH
POINTER_SIZE = $POINTER_SIZE

CC = $CC
CCC = $CCC
AS = $AS
CC_ID = $CC_ID

XP_SYSTEM = $SYSTEM_MACROS
XP_FEATURES = $FEATURE_MACROS
XP_MISC = $MISC_MACROS

CFLAGS = \$(XP_SYSTEM) \$(XP_FEATURES) \$(XP_MISC) -I$XP_DIR
ASFLAGS = $SYSTEM_MACROS -I$XP_DIR
__EOF__
